package com.lw.alarm.task;

import java.util.HashMap;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo;
import com.lw.alarm.factory.FilterFactoryApi;
import com.lw.alarm.filter.FilterChain;
import com.lw.alarm.filter.Response;
import com.lw.alarm.model.AlarmServer;
import com.lw.alarm.model.enums.METHOD;
import com.lw.alarm.model.enums.ServerStatus;
import com.lw.alarm.service.AlarmServerService;
import com.xiaoleilu.hutool.date.DateUtil;
import com.xiaoleilu.hutool.json.JSONObject;
import com.xiaoleilu.hutool.lang.Validator;

/**
 * 
 * 服务监控定时任务
 */

@Component
public class AlarmServerTask {
	private final static Logger logger = LoggerFactory.getLogger(AlarmServerTask.class);
	@Resource
	private AlarmServerService alarmServerService;
	@Resource
	private RestTemplate restTemplate;
	@Resource
	private FilterFactoryApi ff;

	@Scheduled(cron = "${task.alarm.cron})")
	public void findAlarmServerAndHandle() {
		logger.info("服务监控执行开始。。。");
		try {
			ResponseEntity<String> forEntity = restTemplate.getForEntity("https://www.baidu.com/", String.class);
			if (!HttpStatus.OK.equals(forEntity.getStatusCode())) {
				logger.error("=============>网络异常");
				return;
			}
		} catch (RestClientException e) {
			logger.error("网络异常=============>{}");
			return;
		}

		logger.debug("现在时间=============>{}", DateUtil.now());
		PageInfo<AlarmServer> serverList = alarmServerService.findAlarmServerByPage(null, 1, 100);
		logger.debug("集合：=============>{}", JSON.toJSONString(serverList));
		logger.debug("多少页：=============>{}", serverList.getPages());
		serverList.getList().forEach(s -> {
			handle(s);
		});
	}

	@SuppressWarnings("unchecked")
	private void handle(AlarmServer alarmServer) {
		Assert.notNull(alarmServer, "服务对象不能为空");
		Assert.hasLength(alarmServer.getUrl());
		Assert.isTrue(Validator.isUrl(alarmServer.getUrl()), "接口地址不是url!");
		ResponseEntity<JSONObject> forEntity = null;
		HashMap<String, Object> map = null;
		try {
			if (!StringUtils.isEmpty(alarmServer.getParams()))
				map = JSON.parseObject(alarmServer.getParams(), HashMap.class);
		} catch (Exception e) {
			logger.error("=============>", e);
		}
		try {
			switch (METHOD.valueOf(alarmServer.getMethod())) {
			case GET:// get
				forEntity = restTemplate.getForEntity(alarmServer.getUrl(), JSONObject.class, map);
				break;
			case POST:// post
				forEntity = restTemplate.postForEntity(alarmServer.getUrl(), map, JSONObject.class);
				break;
			case PUT:// put
				break;
			case DELETE:// delete
				break;
			default://
				break;
			}
		} catch (RestClientException e) {
			alarmServer.setServerErrorMsg(e.getMessage());
			filterPreHandle(alarmServer);
			logger.error("=============>", e);
			return;
		}
		// 判断http的状态码
		if (HttpStatus.OK != forEntity.getStatusCode()) {
			filterPreHandle(alarmServer);
			return;
		}
		// 验证返回的结果里面的key是否不为空
		JSONObject body = forEntity.getBody();
		if (!StringUtils.isEmpty(alarmServer.getNotNullField())) {
			String[] split = alarmServer.getNotNullField().split(",");
			for (String s : split) {
				if (body.isNull(s) || "[]".equals(body.get(s).toString())) {// key对应值是否为null或无此key
					logger.debug("=============》{}key对应值是为null或无此key{}=======》", alarmServer, s);
					alarmServer.setServerErrorMsg("=========》" + alarmServer.toString() + "key对应值是为null或无此key{}====》"
							+ s + "=====返回的内容：==》" + body);
					filterPreHandle(alarmServer);
					return;
				}
				;
			}
		}
		// 验证返回的结果是否包含这些字段
		if (!StringUtils.isEmpty(alarmServer.getRespResult())) {
			String[] split = alarmServer.getRespResult().split(",");
			for (String s : split) {
				if (!body.toString().contains(s)) {
					logger.debug("=============>{}不包含{}", alarmServer, s);
					alarmServer.setServerErrorMsg("=============》" + alarmServer.toString() + "=========>不包含========>"
							+ s + "===返回的内容：==》" + body);
					filterPreHandle(alarmServer);
					return;
				}
				;
			}

		}
		// 服务器是异常状态的时候，现在到这来，就可以证明服务已经恢复了
		if (ServerStatus.EXCEPTION.value() == alarmServer.getStatus()) {
			FilterChain filterChain = ff.createFilterChain();
			filterChain.doFilter(alarmServer, new Response("====》"), filterChain);
			if (ServerStatus.EXCEPTION.value() == alarmServer.getStatus()) {
				alarmServerService.updateServerStatus(alarmServer.getId(), ServerStatus.NOMAL);
			} else {
				alarmServerService.updateServerStatus(alarmServer.getId(), ServerStatus.EXCEPTION);
			}

		}
		if (alarmServer.getFailureTimes() > 0) {
			alarmServerService.reSetAlarmServerTimes(alarmServer.getId(), alarmServer.getFailureTimes());// 还原已经失败的次数设置为0
		}

	}

	/**
	 * 
	 * @Description:发送短信，邮件，微信的前置处理
	 * @param alarmServer
	 */
	private void filterPreHandle(AlarmServer alarmServer) {
		if (ServerStatus.EXCEPTION.value() == alarmServer.getStatus()) {// 如果服务器是异常状态，就不再次发送了
			return;
		}
		if (verifyMatchingMinTimes(alarmServer)) {
			logger.debug("最少次数{}次没有到达=============>{}", alarmServer.getMinFailureTimes(), alarmServer);
			alarmServerService.incAlarmServerTimes(alarmServer.getId(), alarmServer.getFailureTimes());
			return;
		}
		FilterChain filterChain = ff.createFilterChain();
		filterChain.doFilter(alarmServer, new Response("====》"), filterChain);
		logger.debug("还原已经失败的次数设置为0=============>{}", alarmServer);
		if (ServerStatus.EXCEPTION.value() == alarmServer.getStatus()) {
			alarmServer.setServerErrorMsg("");
			alarmServerService.updateServerStatus(alarmServer.getId(), ServerStatus.NOMAL);
		} else {
			alarmServerService.updateServerStatus(alarmServer.getId(), ServerStatus.EXCEPTION);
		}
		alarmServerService.reSetAlarmServerTimes(alarmServer.getId(), alarmServer.getFailureTimes());// 还原已经失败的次数设置为0
		return;
	}

	/**
	 * 
	 * @Description:验证是否失败次数已经达到设置的最小失败次数
	 * @param alarmServer
	 * @return
	 */
	boolean verifyMatchingMinTimes(AlarmServer alarmServer) {
		return alarmServer.getMinFailureTimes() >= alarmServer.getFailureTimes() + 1 ? true : false;
	}

}